#ifndef PARSER_BASE_H
#define PARSER_BASE_H

#include <wx/arrstr.h>
#include <wx/event.h>
#include <wx/file.h>
#include <wx/filefn.h>
#include <wx/imaglist.h>
#include <wx/string.h>
#include <wx/thread.h>
#include <wx/timer.h>
#include <wx/treectrl.h>

#include "parserthread.h"


typedef std::set<wxString> StringSet;
typedef std::list<wxString> StringList;

namespace ParserCommon {
  enum EFileType {
    ftHeader,
    ftSource,
    ftOther
  };
  EFileType FileType( const wxString& filename, bool force_refresh = false );
}

enum BrowserDisplayFilter {
  bdfFile = 0,
  bdfProject,
  bdfWorkspace,
  bdfEverything
};

enum BrowserSortType {
  bstAlphabet = 0,
  bstKind,
  bstScope,
  bstLine,
  bstNone
};

struct BrowserOptions {
  BrowserOptions():
    showInheritance( false ),
    expandNS( false ),
    treeMembers( true ),
    displayFilter( bdfFile ),
    sortType( bstKind ) {}

  bool showInheritance;
  bool expandNS;
  bool treeMembers;
  BrowserDisplayFilter displayFilter;
  BrowserSortType sortType;
};


struct ParserOptions {
  ParserOptions():
    followLocalIncludes( true ),
    followGlobalIncludes( true ),
    caseSensitive( true ),
    wantPreprocessor( true ),
    useSmartSense( true ),
    whileTyping( true ),
    parseComplexMacros( true ),
    platformCheck( true ),
    storeDocumentation( true ) {}

  bool followLocalIncludes;
  bool followGlobalIncludes;
  bool caseSensitive;
  bool wantPreprocessor;
  bool useSmartSense;
  bool whileTyping;
  bool parseComplexMacros;
  bool platformCheck;
  bool storeDocumentation;
};

class ParserBase : public wxEvtHandler {
    friend class ParserThread;
  public:
    ParserBase();
    virtual ~ParserBase();
    virtual void AddBatchParse( M_Code_unused const StringList& filenames ) { ; }
    virtual void AddParse( M_Code_unused const wxString& filename ) { ; }
    virtual void AddPredefinedMacros( M_Code_unused const wxString& defs ) { ; }
    virtual bool UpdateParsingProject( M_Code_unused M_Code_Project* project ) { return false; }
    virtual bool ParseBuffer( const wxString& buffer, bool isLocal, bool bufferSkipBlocks = false,
                              bool isTemp = false, const wxString& filename = wxEmptyString,
                              int parentIdx = -1, int initLine = 0 );
    virtual bool ParseBufferForFunctions( M_Code_unused const wxString& buffer ) { return false; }
    virtual bool ParseBufferForNamespaces( M_Code_unused const wxString& buffer, M_Code_unused NameSpaceVec& result ) { return false; }
    virtual bool ParseBufferForUsingNamespace( M_Code_unused const wxString& buffer, M_Code_unused wxArrayString& result,
        M_Code_unused bool bufferSkipBlocks = true ) { return false; }
    virtual bool Reparse( M_Code_unused const wxString& filename, M_Code_unused bool isLocal = true );
    virtual bool AddFile( M_Code_unused const wxString& filename, M_Code_unused M_Code_Project* project, M_Code_unused bool isLocal = true ) { return false; }
    virtual bool RemoveFile( M_Code_unused const wxString& filename ) { return false; }
    virtual bool IsFileParsed( M_Code_unused const wxString& filename ) { return false; }
    virtual bool Done() { return true; }
    virtual wxString NotDoneReason() { return wxEmptyString; }
    virtual TokenTree* GetTokenTree() const;
    TokenTree* GetTempTokenTree() { return m_TempTokenTree; }
    virtual const wxString GetPredefinedMacros() const { return wxEmptyString; }
    void AddIncludeDir( const wxString& dir );
    const wxArrayString& GetIncludeDirs() const { return m_IncludeDirs; }
    wxString GetFullFileName( const wxString& src, const wxString& tgt, bool isGlobal );
    wxArrayString FindFileInIncludeDirs( const wxString& file, bool firstonly = false );
    virtual void ReadOptions() {}
    virtual void WriteOptions() {}
    virtual ParserOptions&  Options() { return m_Options; }
    virtual BrowserOptions& ClassBrowserOptions() { return m_BrowserOptions; }
    size_t FindTokensInFile( const wxString& filename, TokenIdxSet& result, short int kindMask );
  private:
    virtual bool ParseFile( const wxString& filename, bool isGlobal, bool locked = false );
    wxString FindFirstFileInIncludeDirs( const wxString& file );
  protected:
    TokenTree* m_TokenTree;
    TokenTree* m_TempTokenTree;
    ParserOptions m_Options;
    BrowserOptions m_BrowserOptions;
  private:
    SearchTree<wxString> m_GlobalIncludes;
    wxArrayString m_IncludeDirs;
};

#endif
